package com.ceo.common.controller;

import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.WriteTable;
import com.alibaba.excel.write.metadata.WriteWorkbook;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ceo.common.export.TableOption;
import com.ceo.common.http.response.DefaultResponse;
import com.ceo.common.query.QueryCondition;
import com.ceo.common.query.QueryParameter;
import com.ceo.common.utils.DateUtil;
import com.ceo.common.utils.EntityUtil;
import com.ceo.common.utils.EnvUtil;
import com.ceo.common.utils.PropertiesUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * @author uto_dev_008
 * @desc
 * @since 2021/11/22 14:54
 * Copyright (c)  All rights reserved
 */
public class BaseController<K extends BaseMapper<T>, T> {
    private static final Logger logger = LoggerFactory.getLogger(BaseController.class);

    private QueryParameter queryParameter;


    protected String getPara(String name) {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String result = request.getParameter(name);
        return "".equals(result) ? null : result;
    }

    protected Integer getParaToInt(String name, Integer defaultValue) {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        return toInt(request.getParameter(name), defaultValue);
    }

    protected static int toInt(String value, int defaultValue) {
        try {
            if (value == null || "".equals(value.trim()))
                return defaultValue;
            value = value.trim();
            if (value.startsWith("N") || value.startsWith("n"))
                return -Integer.parseInt(value.substring(1));
            return Integer.parseInt(value);
        } catch (Exception e) {
        }
        return defaultValue;
    }

    protected <T> T getObjectFromJson(String name, Class<T> objectClass) {

        String value = getPara(name);
        if (StrUtil.isBlank(value))
            return null;
        return JSON.parseObject(value, objectClass);
    }

    protected QueryParameter getQueryParameter() {
        if (queryParameter != null)
            return queryParameter;
        QueryParameter qp = new QueryParameter();
        Map<String, Object> _params = getObjectFromJson("_params", Map.class);
        if (_params != null) {
            for (String key : _params.keySet())
                qp.addParamter(key, _params.get(key));
        }
        Map<String, String> _conditions = getObjectFromJson("_conditions", Map.class);
        if (_conditions != null) {
            for (String key : _conditions.keySet()) {
                try {
                    QueryCondition qc = QueryCondition.valueOf(_conditions.get(key));
                    qp.addCondition(key, qc);
                } catch (Exception e) {
                    logger.warn("查询参数[" + key + "]使用的表达式[" + _conditions.get(key) + "]不在表达式枚举的范围内,已作为equal默认值!");
                }
            }
        }

        qp.setSortField(getPara("sortField"));
        qp.setSortOrder(getPara("sortOrder"));
        qp.setPager(getParaToInt("pageIndex", 1), getParaToInt("pageSize", 20));

        return queryParameter = qp;
    }

    protected DefaultResponse renderTable(Object obj) {
        if (obj == null) {
            return DefaultResponse.success();
        }
        if (StrUtil.isNotBlank(getPara("export")) && getPara("export").equalsIgnoreCase("export")) {
            List data = null;
            if (obj instanceof Page)
                data = ((Page) obj).getRecords();
            else if (obj instanceof List)
                data = (List) obj;
            String _headers = getPara("_headers");
            List<Map> headerConfig = JSONObject.parseObject(_headers, List.class);
            TableOption gei = new TableOption(headerConfig);
            gei.setData(data);
            String _exportFile = getPara("_exportFile");
            List<TableOption> sheets = new ArrayList<>();
            sheets.add(gei);
            return renderExcel(sheets, _exportFile);
        } else {
            return DefaultResponse.success(obj);
        }
    }

    protected DefaultResponse renderExcel(List<TableOption> sheets, String fileName) {
        try {
            String tempPath = System.getProperty("java.io.tmpdir") + PropertiesUtil.getString("server.servlet.context-path", "/")
                    + File.separator + DateUtil.getTodayDayString();
            File tempPathFile = new File(tempPath);
            if (!tempPathFile.exists())
                tempPathFile.mkdirs();
            String tempFile = tempPath + File.separator + "export_" + EntityUtil.createUUIDNoSeparator() + ".xlsx";
            OutputStream out = new FileOutputStream(tempFile);
            WriteWorkbook writeWorkbook = new WriteWorkbook();
            writeWorkbook.setOutputStream(out);
            writeWorkbook.setExcelType(ExcelTypeEnum.XLSX);
            writeWorkbook.setNeedHead(true);
            ExcelWriter writer = new ExcelWriter(writeWorkbook);
            for (int i = 1; i <= sheets.size(); i++) {
                TableOption to = sheets.get(i - 1);
                WriteSheet sheet = new WriteSheet();
                sheet.setSheetNo(i);
                sheet.setSheetName(to.getSheetName());
                WriteTable table = new WriteTable();
                table.setTableNo(i);
                table.setHead(to.getEasyHeader());
                writer.write(to.getEasyData(), sheet, table);
            }
            writer.finish();
            Map<String, String> ret = new HashMap<>();
            ret.put("fileId",
                    Base64.getEncoder().
                            encodeToString(String.format("%s@%s@%s", EnvUtil.getCurUserObject().getId(), fileName, tempFile).getBytes(StandardCharsets.UTF_8)));
            return DefaultResponse.success(ret);
        } catch (Exception e) {
            logger.error(e.getMessage());
            return DefaultResponse.error(10000005);
        }
    }

}
